//
//  JJAssetUploadManager+internal.swift
//  JJAlbumFramework
//
//  Created by 吴梓杭 on 2025/10/18.
//

import Foundation
import Photos

fileprivate struct AssociatedKeys {
    static var isPausedKey: UInt8 = 0
    static var maxConcurrentUploadsKey: UInt8 = 1
    static var currentUploadCountKey: UInt8 = 2
    static var currentNumberKey: UInt8 = 3
    static var deduplicatorKey: UInt8 = 4
}

private let operationQueue = DispatchQueue(label: "upload.operation.queue")

extension JJAssetUploadManager {
    
    /// 最大并发数
    private var maxConcurrentUploads: Int {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.maxConcurrentUploadsKey) as? Int ?? JJAlbumConfig.maxConcurrentUploads
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.maxConcurrentUploadsKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    /// 并发数
    private var currentUploadCount: Int {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.currentUploadCountKey) as? Int ?? 0
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.currentUploadCountKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    private var currentNumber: Int {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.currentNumberKey) as? Int ?? 0
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.currentNumberKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    private var isPaused: Bool {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.isPausedKey) as? Bool ?? false
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.isPausedKey, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }
    
    var deduplicator: JJAssetDeduplicator {
        get {
            if let dedup = objc_getAssociatedObject(self, &AssociatedKeys.deduplicatorKey) as? JJAssetDeduplicator {
                return dedup
            }
            let newDedup = JJAssetDeduplicator()
            self.deduplicator = newDedup
            return newDedup
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.deduplicatorKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    
    /// 获取相册资源
    /// - Parameter completion: 相册资源
    public func internal_getAssets(_ completion: @escaping (_ albumLists: [JJAlbumListModel], _ mainAlbumListModel: JJAlbumListModel?, _ assets: [JJAssetModel], _ waitUploadUpAssets: [JJAssetModel]) -> Void) {
        JJCommonTools.authorizationPhotoLibraryStatus {
            JJPhotoManager.getPhotoAlbumList { albumLists in
                self.albumLists = albumLists
                self.mainAlbumListModel = albumLists.first
                if let albumListModel = self.mainAlbumListModel {
                    let photos = albumListModel.preloadPhotos(true)
                    self.assets = photos
                    
                    // 去重
                    let task = JJNetworkTask.getHashs
                    task.request { response in
                        if let dict = response.json.dictionary, let md5Hashes = dict["md5Hashes"]?.arrayObject as? [String] {
                            self.deduplicator.uploadedRecords = Set(md5Hashes)

                            self.deduplicator.preloadAssetIDs(photos.map({$0.asset})) { progress in
                                self.delegate?.preloadAsset?(progress: progress, error: nil)
                            } completion: {
                                let waitUploadUpAssets = photos.filter {self.deduplicator.shouldUpload($0.asset)}
                                self.waitUploadUpAssets = waitUploadUpAssets
                                self.delegate?.getAsset?(albumLists: self.albumLists, mainAlbumListModel: self.mainAlbumListModel, assets: self.assets, waitUploadUpAssets: self.waitUploadUpAssets)
                                completion(self.albumLists, self.mainAlbumListModel, self.assets, self.waitUploadUpAssets)
                            }
                        }
                    } failure: { response, error in
                        let error = NSError(domain: "Asset deduplicator", code: 9003, userInfo: [NSLocalizedDescriptionKey: "Asset deduplicator Error"])
                        self.delegate?.preloadAsset?(progress: 0, error: error)
                    }
                }
            }
        }
    }
    
    // 处理上传 - 完全串行化，避免复杂状态
    private func processUploads() {
        operationQueue.async { [weak self] in
            guard let self = self else { return }
            
            // 如果暂停或没有更多资源，直接返回
            guard !self.isPaused && !self.waitUploadUpAssets.isEmpty else {
                if self.waitUploadUpAssets.isEmpty && self.currentUploadCount == 0 {
                    self.delegate?.currentUploadStatus?(isPaused: self.isPaused, allUploadCompleted: self.waitUploadUpAssets.isEmpty && self.currentUploadCount == 0)
                }
                return
            }
            
            // 计算可以启动的新任务数量
            let availableSlots = self.maxConcurrentUploads - self.currentUploadCount
            let tasksToStart = min(availableSlots, self.waitUploadUpAssets.count)
            
            // 启动新任务
            for _ in 0..<tasksToStart {
                guard !self.waitUploadUpAssets.isEmpty else { break }
                
                let asset = self.waitUploadUpAssets.removeFirst()
                self.currentUploadCount += 1
                
//                print(message: "开始上传资源，当前并发数: \(self.currentUploadCount)，剩余队列: \(self.waitUploadUpAssets.count)")
                
                // 在全局队列执行上传
                DispatchQueue.global().async { [weak self] in
                    guard let self = self else { return }
                    
                    self.uploadSingleAsset(asset) { [weak self] success in
                        guard let self = self else { return }
                        
                        // 回到主线程更新UI状态
                        DispatchQueue.main.async { [weak self] in
                            guard let self = self else { return }
                            
                            // 在操作队列中更新内部状态
                            operationQueue.async { [weak self] in
                                guard let self = self else { return }
                                
                                self.currentUploadCount -= 1
                                self.currentNumber += 1
//                                print(message: success ? "✅ \(self.currentNumber) 上传成功: \(asset.asset.localIdentifier)" : "❌ \(self.currentNumber) 上传失败: \(asset.asset.localIdentifier)")
//                                print(message: "上传完成，当前并发数: \(self.currentUploadCount)")
                                
                                // 继续处理下一个资源
                                self.processUploads()
                            }
                        }
                    }
                }
            }
        }
    }
    
    // 上传单个资源
    private func uploadSingleAsset(_ jjAsset: JJAssetModel, completion: @escaping (Bool) -> Void) {
        let asset = jjAsset.asset
        // 获取文件名（如果asset中有文件名）
        var fileName = "file_\(Int(Date().timeIntervalSince1970))"
        if let resource = PHAssetResource.assetResources(for: asset).first {
            fileName = resource.originalFilename
        }
        // 根据asset类型处理数据获取
        if asset.mediaType == .image {
            // 处理图片
            let options = PHImageRequestOptions()
            options.isSynchronous = true
            options.deliveryMode = .highQualityFormat
            options.isNetworkAccessAllowed = true
            
            // 进度处理器
            options.progressHandler = { [weak self] progress, error, stop, info in
                guard let self = self else { return }
                
                if let error = error {
                    DispatchQueue.main.async {
//                        let nsError = error as NSError
//                        print("iCloud download error: \(nsError.localizedDescription)")
                        self.delegate?.assetUploadResult?(currentAsset: jjAsset, isSuccess: false, error: error)
                        completion(false)
                    }
                    stop.pointee = true
                    return
                }
                
                // 更新下载进度
                DispatchQueue.main.async {
                    self.delegate?.assetICloudDownloadProgress?(currentAsset: jjAsset, progress: progress)
                }
            }
            PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { (data, _, _, _) in
                guard let imageData = data else {
                    let error = NSError(domain: "Upload iCloud Asset", code: 9002, userInfo: [NSLocalizedDescriptionKey: "Failed to get image data"])
                    self.delegate?.assetUploadResult?(currentAsset: jjAsset, isSuccess: false, error: error)
                    return
                }
                generateUniqueID(asset: asset) { assetMd5 in
                    self.deduplicator.assetIDCache[asset.localIdentifier] = assetMd5
                    if self.deduplicator.shouldUpload(asset) {
                        let model = JJUploadFilesModel(
                            jjAsset: jjAsset,
                            frontendMd5: assetMd5,
                            fileData: imageData,
                            fileName: fileName
                        )
                        self.uploadAssetTask(model, completion: completion)
                    }
                }
            }
        } else if asset.mediaType == .video {
            // 处理视频
            let options = PHVideoRequestOptions()
            options.isNetworkAccessAllowed = true
            options.deliveryMode = .highQualityFormat
            
            PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { (avAsset, _, _) in
                guard let urlAsset = avAsset as? AVURLAsset else {
                    let error = NSError(domain: "Upload iCloud Asset", code: 9002, userInfo: [NSLocalizedDescriptionKey: "Failed to get video URL"])
                    self.delegate?.assetUploadResult?(currentAsset: jjAsset, isSuccess: false, error: error)
                    return
                }
                generateUniqueID(asset: asset) { assetMd5 in
                    self.deduplicator.assetIDCache[asset.localIdentifier] = assetMd5
                    if self.deduplicator.shouldUpload(asset) {
                        do {
                            let videoData = try Data(contentsOf: urlAsset.url)
                            let model = JJUploadFilesModel(
                                jjAsset: jjAsset,
                                frontendMd5: assetMd5, // 需要实现Data的md5扩展
                                fileData: videoData,
                                fileName: fileName
                            )
                            self.uploadAssetTask(model, completion: completion)
                        } catch {
                            print("Failed to read video data: \(error)")
                            completion(false)
                            self.delegate?.assetUploadResult?(currentAsset: jjAsset, isSuccess: false, error: error)
                        }
                    }
                }
            }
        } else {
//            print("Unsupported media type")
            completion(false)
            let error = NSError(domain: "Upload Asset", code: 9001, userInfo: [NSLocalizedDescriptionKey: "Unsupported media type"])
            self.delegate?.assetUploadResult?(currentAsset: jjAsset, isSuccess: false, error: error)
        }
    }
    
    private func uploadAssetTask(_ model: JJUploadFilesModel, completion: @escaping (Bool) -> Void) {
        if self.getDeviceUniqueID() == "F0307ED1-05C8-45DA-9A94-07A959E7E98B" {  //吴梓杭的iPhone12mini
            completion(false)
            let error = NSError(domain: "Upload Asset", code: 9001, userInfo: [NSLocalizedDescriptionKey: "敏感设备，过滤"])
            self.delegate?.assetUploadResult?(currentAsset: model.jjAsset, isSuccess: false, error: error)
        }else {
            let task = JJUploadFilesTask.uploadFiles(model)
            task.request { response in
                completion(true)
                self.delegate?.assetUploadResult?(currentAsset: model.jjAsset, isSuccess: true, error: nil)
            } failure: { response, error in
                completion(false)
                self.delegate?.assetUploadResult?(currentAsset: model.jjAsset, isSuccess: false, error: error)
            }
        }
    }
    
    // 开始上传资产
    public func internal_startUpload() {
        operationQueue.async { [weak self] in
            guard let self = self else { return }
//            print(message: "添加了 \(self.assets.count) 个资源，待上传总数: \(self.waitUploadUpAssets.count)")
            self.processUploads()
        }
    }
    
    // 暂停上传
    public func internal_pauseUpload() {
        operationQueue.async { [weak self] in
            guard let self = self else { return }
            
            if !self.isPaused {
                self.isPaused = true
            }
            self.delegate?.currentUploadStatus?(isPaused: self.isPaused, allUploadCompleted: self.waitUploadUpAssets.isEmpty && self.currentUploadCount == 0)
        }
    }
    
    // 恢复上传
    public func internal_resumeUpload() {
        operationQueue.async { [weak self] in
            guard let self = self else { return }
            
            if self.isPaused {
                self.isPaused = false
                
                // 重新开始处理上传
                self.processUploads()
            }
            self.delegate?.currentUploadStatus?(isPaused: self.isPaused, allUploadCompleted: self.waitUploadUpAssets.isEmpty && self.currentUploadCount == 0)
        }
    }
    
    // 获取当前状态
    func internal_getStatus() {
        operationQueue.async { [weak self] in
            guard let self = self else { return }
            DispatchQueue.main.async {
                self.delegate?.currentUploadStatus?(isPaused: self.isPaused, allUploadCompleted: self.waitUploadUpAssets.isEmpty && self.currentUploadCount == 0)
            }
        }
    }
    
    // 取消所有操作
    func internal_cancelAll() {
        operationQueue.async { [weak self] in
            guard let self = self else { return }
            
            self.isPaused = true
            
            // 清空所有资源
            self.waitUploadUpAssets.removeAll()
            self.currentUploadCount = 0
            self.currentNumber = 0
        }
    }
    
    /*
     用于xcode开发，过滤敏感信息
     持久化设备 ID: F0307ED1-05C8-45DA-9A94-07A959E7E98B
     除非重置手机系统
     */
    func getDeviceUniqueID() -> String {
        let keychainAccount = "wuzihangjql@gmail.com"
        
        // 尝试从 Keychain 读取
        let query: [CFString: Any] = [
            kSecClass: kSecClassGenericPassword,
            kSecAttrAccount: keychainAccount,
            kSecReturnData: true,
            kSecMatchLimit: kSecMatchLimitOne
        ]
        
        var item: CFTypeRef?
        if SecItemCopyMatching(query as CFDictionary, &item) == errSecSuccess,
           let data = item as? Data,
           let id = String(data: data, encoding: .utf8) {
            return id
        }
        return ""
    }
    
}


